package com.ss.android.article.base.feature.main;

import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentManager;

import com.bytedance.article.common.a.g;
import com.bytedance.common.utility.Logger;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;

import org.json.JSONObject;

public final class FragmentManagerWrapper extends FragmentManager {
    private FragmentManager mFragmentManager;

    public FragmentManagerWrapper(@NonNull FragmentManager fragmentManager) {
        this.mFragmentManager = fragmentManager;
    }

    public final Fragment findFragmentById(@IdRes int id) {
        return this.mFragmentManager.findFragmentById(id);
    }

    public final Fragment findFragmentByTag(String tag) {
        return this.mFragmentManager.findFragmentByTag(tag);
    }

    @Override
    public void popBackStack() {
        this.mFragmentManager.popBackStack();
    }

    public final FragmentTransaction beginTransaction() {
        return this.mFragmentManager.beginTransaction();
    }

    public final void popBackStack(int id, int flags) {
        try {
            this.mFragmentManager.popBackStack(id, flags);
        } catch (Throwable throwable) {
            this.printStackTrace("exception_popBackStack");
            Logger.throwExceptionInDebug(throwable);
        }
    }

    @Override
    public boolean popBackStackImmediate(int id, int flags) {
        return this.mFragmentManager.popBackStackImmediate(id, flags);
    }

    @Override
    public int getBackStackEntryCount() {
        return mFragmentManager.getBackStackEntryCount();
    }

    @Override
    public BackStackEntry getBackStackEntryAt(int index) {
        return this.mFragmentManager.getBackStackEntryAt(index);
    }

    @Override
    public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
        this.mFragmentManager.addOnBackStackChangedListener(listener);
    }

    @Override
    public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
        this.mFragmentManager.removeOnBackStackChangedListener(listener);
    }

    @Override
    public void putFragment(Bundle bundle, String key, Fragment fragment) {
        this.mFragmentManager.putFragment(bundle, key, fragment);
    }

    @Override
    public Fragment getFragment(Bundle bundle, String key) {
        return this.mFragmentManager.getFragment(bundle, key);
    }

    @Override
    public List<Fragment> getFragments() {
        return this.mFragmentManager.getFragments();
    }

    @Override
    public Fragment.SavedState saveFragmentInstanceState(Fragment f) {
        return this.mFragmentManager.saveFragmentInstanceState(f);
    }

    @Override
    public boolean isDestroyed() {
        return this.mFragmentManager.isDestroyed();
    }

    public final void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        this.mFragmentManager.dump(prefix, fd, writer, args);
    }

    private void printStackTrace(String errorMessage) {
        try {
            StackTraceElement[] elements = new Exception(errorMessage).getStackTrace();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 1; i < Math.min(8, elements.length); ++i) {
                if (i > 1) {
                    stringBuilder.append("\n");
                }
                String className = elements[i].getClassName();
                int indexOfLastDot = className.lastIndexOf(46);
                if (indexOfLastDot >= 0) {
                    className = className.substring(indexOfLastDot + 1);
                }

                stringBuilder.append(className);
                stringBuilder.append(".");
                stringBuilder.append(elements[i].getMethodName());
            }

            String call_stack = stringBuilder.toString();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("instance", this);
            jsonObject.put("call_stack", call_stack);
            g.a("main_fragment_manager", jsonObject);
            Logger.d("FragmentManagerWrapper", errorMessage + "\t\n" + call_stack);
        } catch (Throwable throwable) {
            Logger.throwExceptionInDebug(throwable);
        }
    }

    public final boolean executePendingTransactions() {
        boolean result = false;
        try {
            result = this.mFragmentManager.executePendingTransactions();
        } catch (Throwable throwable) {
            this.printStackTrace("exception_executePendingTransactions");
            Logger.throwExceptionInDebug(throwable);
        }
        return result;
    }

    public final boolean popBackStackImmediate() {
        return this.mFragmentManager.popBackStackImmediate();
    }

    @Override
    public void popBackStack(String name, int flags) {
        this.mFragmentManager.popBackStack(name, flags);
    }

    @Override
    public boolean popBackStackImmediate(String name, int flags) {
        return this.mFragmentManager.popBackStackImmediate(name, flags);
    }
}

